package gui2

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/gdamore/tcell/v2"
	"github.com/rivo/tview"
	"gopkg.in/yaml.v2"

	"baikai/ptkGUI/gui"
	v1 "baikai/ptkGUI/models"
)

// Gui have all panels
type Gui struct {
	app             *tview.Application
	pages           *tview.Pages
	rightPanel      *tview.Grid
	globalPage      *tview.Grid
	advancedPage    *tview.Grid
	dbAdvancedPages map[string]*tview.Grid
	dbPage          map[string]*tview.Grid
	cmPage          map[string]*tview.Grid
	addCMButton     *tview.Button

	dbServerNode *tview.TreeNode
	cmServerNode *tview.TreeNode

	isInstallCM bool
	/**/
	// conf *v1.Config
	globalInfo *v1.Global
	dbServers  map[string]*v1.DBServer
	cmServers  map[string]*v1.CMServer
}

func New() *Gui {
	rightPanel := tview.NewGrid()
	rightPanel.SetRows(0). // 主体行数设置为1行，动态填充
				SetColumns(0, 1).SetBorder(true)

	global := new(v1.Global)
	global.EnvMap = make(map[string]string)
	return &Gui{
		app:             tview.NewApplication(),
		pages:           tview.NewPages(),
		rightPanel:      rightPanel,
		dbPage:          make(map[string]*tview.Grid),
		cmPage:          make(map[string]*tview.Grid),
		dbAdvancedPages: map[string]*tview.Grid{},
		globalInfo:      global,
		dbServers:       make(map[string]*v1.DBServer),
		dbServerNode:    tview.NewTreeNode("数据库列表"),
		cmServers:       make(map[string]*v1.CMServer),
		cmServerNode:    tview.NewTreeNode("CM 列表"),
	}
}

func (g *Gui) Start() error {
	// 左侧树状结构
	treeView := g.createTreeView()

	// 创建布局 Grid
	grid := tview.NewGrid().
		SetRows(3, 0, 0).  // 设置行，分别为：按钮行、树状结构行、内容行
		SetColumns(30, 0). // 设置列，分别为：左侧树结构列、右侧内容列
		SetBorders(true)   // 显示网格边界

	// 左上角的按钮
	exitButton := tview.NewButton("退出").SetSelectedFunc(func() {
		g.app.Stop()
	})
	exitButton.SetLabelColor(tcell.ColorRed)

	saveButton := tview.NewButton("保存").SetSelectedFunc(func() {
		dbServers := []*v1.DBServer{}
		for _, dbServer := range g.dbServers {
			dbServers = append(dbServers, dbServer)
		}
		cmServers := []*v1.CMServer{}
		for _, cmServer := range g.cmServers {
			cmServers = append(cmServers, cmServer)
		}
		config := &v1.Config{
			Global:     g.globalInfo,
			DBServers:  dbServers,
			CMServers:  cmServers,
			CreateTime: time.Now(),
			UpdateTime: time.Now(),
			Comment:    "ptk-gui",
		}

		data, err := yaml.Marshal(&config)
		if err != nil {
			log.Printf("Error while marshaling. %v", err)
			return
		}

		// 将 YAML 数据写入文件
		err = os.WriteFile("config.yaml", data, 0644)
		if err != nil {
			log.Printf("Error while writing to file. %v", err)
			return
		}

		log.Println("YAML file created successfully!")
		g.app.Stop()
	})
	saveButton.SetLabelColor(tcell.Color191)
	buttons := tview.NewFlex().AddItem(returnButtonGrid(exitButton), 0, 1, false).AddItem(returnButtonGrid(saveButton), 0, 1, false)

	// 将各个部分添加到Grid中
	grid.AddItem(buttons, 0, 0, 1, 1, 0, 0, false) // 按钮行，跨越两列
	grid.AddItem(treeView, 1, 0, 2, 1, 0, 0, true) // 树结构，跨越两行
	grid.AddItem(g.pages, 0, 1, 3, 1, 0, 0, true)

	if err := g.app.SetRoot(grid, true).EnableMouse(true).Run(); err != nil {
		return err
	}
	return nil
}

// createTreeView 创建左侧的树状结构
func (g *Gui) createTreeView() *tview.TreeView {
	rootNode := tview.NewTreeNode(".").SetSelectedFunc(func() {
		// 放个图片
	})

	globalNode := tview.NewTreeNode("全局配置").SetSelectedFunc(func() {
		g.showGlobalPage()
	})
	//
	// // 高级选项
	// advTreeNode := tview.NewTreeNode("高级选项").SetSelectedFunc(func() {
	// 	g.showAdvancedOptions()
	// })
	// // 新增数据库实例
	// addInstanceTreeNode := tview.NewTreeNode("新增数据库实例").SetSelectedFunc(func() {
	// 	g.showAddDBInstance()
	// })
	// globalNode.AddChild(advTreeNode).AddChild(addInstanceTreeNode)

	rootNode.AddChild(globalNode).AddChild(g.dbServerNode).AddChild(g.cmServerNode)

	treeView := tview.NewTreeView()
	treeView.SetRoot(rootNode).
		SetCurrentNode(rootNode).
		SetBorder(true)

	return treeView
}

func (g *Gui) showGlobalPage() {
	if g.globalPage == nil {
		g.createGlobalPage()
	}

	g.rightPanel.Clear().SetColumns(0, 0).AddItem(g.globalPage, 0, 0, 1, 2, 0, 0, true)

	// 添加 rightPanel 到 pages 中
	g.pages.RemovePage("rightPanel")
	g.pages.AddPage("rightPanel", g.rightPanel, true, true)
	g.pages.SwitchToPage("rightPanel")
	g.app.SetFocus(g.globalPage)
}

func (g *Gui) createGlobalPage() {
	// 全局配置表单
	globalForm := g.createGlobalForm()

	// 按钮
	advancedButton := tview.NewButton("高级选项").SetSelectedFunc(func() {
		g.showAdvancedOptions()
	})
	addDBButton := tview.NewButton("新增数据库实例").SetSelectedFunc(func() {
		g.showAddDBInstance()
	})
	addCMButton := tview.NewButton("新增CM实例").SetSelectedFunc(func() {
		g.showAddCMInstance()
	})
	// addCMTree := tview.NewTreeNode("新增CM实例").SetSelectedFunc(func() {
	// 	g.showAddCMInstance()
	// })

	addCMButton.SetDisabled(true)
	g.addCMButton = addCMButton
	// 将表单和按钮放到Grid中
	g.globalPage = tview.NewGrid().
		SetRows(17, 1, 1, 1, 1, 1, 1).
		SetColumns(1, 2, 1, 1, 10).
		AddItem(globalForm, 0, 0, 1, 12, 0, 0, true).
		AddItem(advancedButton, 2, 1, 1, 4, 0, 0, true).
		AddItem(addDBButton, 4, 1, 1, 4, 0, 0, true).
		AddItem(g.addCMButton, 6, 1, 1, 4, 0, 0, true)
}

func (g *Gui) createGlobalForm() *tview.Form {
	f := tview.NewForm()
	f.AddInputField("集群名", "", 20, nil, func(text string) {
		g.globalInfo.ClusterName = text
	})

	g.globalInfo.User = "omm"
	g.globalInfo.Group = "omm"

	userInput := tview.NewInputField().SetLabel("用户名").SetFieldWidth(20).SetText(g.globalInfo.User)
	groupInput := tview.NewInputField().SetLabel("用户名").SetFieldWidth(20).SetText(g.globalInfo.Group)

	userInput.SetChangedFunc(func(text string) {
		g.globalInfo.User = text
		groupInput.SetText(text)
	})
	groupInput.SetChangedFunc(func(text string) {
		g.globalInfo.Group = text
	})

	f.AddFormItem(userInput).AddFormItem(groupInput)

	f.AddInputField("数据库端口", "26000", 20, g.checkNum, func(text string) {
		if number, err := strconv.Atoi(text); err == nil {
			g.globalInfo.DBPort = number
		}
	})

	f.AddInputField("用户密码", "", 20, nil, func(text string) {
		//
	})
	f.AddInputField("数据库密码", "", 20, nil, nil)

	f.AddInputField("安装目录", "", 20, nil, func(text string) {
		g.globalInfo.BaseDir = text
	})

	f.AddCheckbox("是否安装CM", false, func(checked bool) {
		g.addCMButton.SetDisabled(!checked)
		g.isInstallCM = checked
	})
	return f
}

// showAdvancedOptions 显示高级选项
func (g *Gui) showAdvancedOptions() {
	// 如果 advancedPage 不存在，创建它
	if g.advancedPage == nil {
		g.globalInfo.AppDir = filepath.Join(g.globalInfo.BaseDir, "app")
		g.globalInfo.DataDir = filepath.Join(g.globalInfo.BaseDir, "dada")
		g.globalInfo.LogDir = filepath.Join(g.globalInfo.BaseDir, "log")
		g.globalInfo.ToolDir = filepath.Join(g.globalInfo.BaseDir, "tool")
		g.globalInfo.TmpDir = filepath.Join(g.globalInfo.BaseDir, "tmp")
		generalForm := tview.NewForm().
			AddInputField("数据库路径", g.globalInfo.AppDir, 20, nil, func(text string) {
				g.globalInfo.AppDir = text
			}).
			AddInputField("数据库存储目录", g.globalInfo.DataDir, 20, nil, func(text string) {
				g.globalInfo.DataDir = text
			}).
			AddInputField("数据库日志目录", g.globalInfo.LogDir, 20, nil, func(text string) {
				g.globalInfo.LogDir = text
			}).
			AddInputField("数据库工具目录", g.globalInfo.ToolDir, 20, nil, func(text string) {
				g.globalInfo.ToolDir = text
			}).
			AddInputField("数据库临时目录", g.globalInfo.TmpDir, 20, nil, func(text string) {
				g.globalInfo.TmpDir = text
			})

		sshOption := &v1.SSHOption{
			Port:        22,
			User:        "root",
			ConnTimeout: 60 * time.Second,
			ExecTimeout: 600 * time.Second,
		}

		sshPort := tview.NewInputField().SetLabel("服务器端口").SetText(strconv.Itoa(sshOption.Port)).SetFieldWidth(20).SetChangedFunc(func(text string) {
			port, err := strconv.Atoi(text)
			if err == nil {
				sshOption.Port = port
			}
		}).SetDisabled(true)
		sshUser := tview.NewInputField().SetLabel("登录用户").SetText(sshOption.User).SetFieldWidth(20).SetChangedFunc(func(text string) {
			sshOption.User = text
		}).SetDisabled(true)
		sshPasswd := tview.NewInputField().SetLabel("登录密码").SetFieldWidth(20).SetChangedFunc(func(text string) {
			sshOption.Password = text
		}).SetDisabled(true)
		sshKeyFile := tview.NewInputField().SetLabel("秘钥文件路径").SetFieldWidth(20).SetChangedFunc(func(text string) {
			sshOption.KeyFile = text
		}).SetDisabled(true)
		sshConnect := tview.NewInputField().SetLabel("超时时间(m)").SetText(durationToMinutesStr(sshOption.ConnTimeout)).SetFieldWidth(20).SetChangedFunc(func(text string) {
			duration, err := stringToDuration(text)
			if err == nil {
				sshOption.ConnTimeout = duration
			}
		}).SetDisabled(true)
		sshExecTime := tview.NewInputField().SetLabel("执行超时时间(m)").SetText(durationToMinutesStr(sshOption.ExecTimeout)).SetFieldWidth(20).SetChangedFunc(func(text string) {
			duration, err := stringToDuration(text)
			if err == nil {
				sshOption.ExecTimeout = duration
			}
		}).SetDisabled(true)

		sshGeneralCheckBox := tview.NewCheckbox().SetLabel("连接信息")
		sshGeneralCheckBox.SetChangedFunc(func(checked bool) {
			sshPort.SetDisabled(!checked)
			sshUser.SetDisabled(!checked)
			sshPasswd.SetDisabled(!checked)
			sshKeyFile.SetDisabled(!checked)
			sshConnect.SetDisabled(!checked)
			sshExecTime.SetDisabled(!checked)
			if checked {
				g.globalInfo.SSHOption = sshOption
			} else {
				g.globalInfo.SSHOption = nil
			}
		})

		// hba
		hbaCheckBox := tview.NewCheckbox().SetLabel("HBA白名单")

		hbaConf := &v1.HBAConf{
			Type:     "host",
			Database: "all",
			User:     "all",
			Method:   "md5",
		}
		hbaTypes := []string{"local", "host", "hostssl", "hostnossl"}
		hbaMethods := []string{"trust", "reject", "md5", "sha256", "sm3", "cert", "gss", "peer"}
		hbaType := tview.NewDropDown().SetOptions(hbaTypes, nil).
			SetLabel("连接类型").SetCurrentOption(1).
			SetFieldWidth(20).SetSelectedFunc(func(text string, index int) {
			hbaConf.Type = text
		}).SetDisabled(true)
		hbaDBName := tview.NewInputField().SetLabel("数据库名称").SetText(hbaConf.Database).SetFieldWidth(20).SetChangedFunc(func(text string) {
			hbaConf.Database = text
		}).SetDisabled(true)
		hbaDBUser := tview.NewInputField().SetLabel("数据库用户").SetText(hbaConf.User).SetFieldWidth(20).SetChangedFunc(func(text string) {
			hbaConf.User = text
		}).SetDisabled(true)
		hbaAddress := tview.NewInputField().SetLabel("客户端地址").SetText("").SetFieldWidth(20).SetChangedFunc(func(text string) {
			hbaConf.Address = text
		}).SetDisabled(true)
		hbaMethod := tview.NewDropDown().SetOptions(hbaMethods, nil).
			SetLabel("认证方法").SetCurrentOption(3).
			SetFieldWidth(20).SetSelectedFunc(func(text string, index int) {
			hbaConf.Method = text
		}).SetDisabled(true)

		hbaCheckBox.SetChangedFunc(func(checked bool) {
			hbaType.SetDisabled(!checked)
			hbaDBName.SetDisabled(!checked)
			hbaDBUser.SetDisabled(!checked)
			hbaAddress.SetDisabled(!checked)
			hbaMethod.SetDisabled(!checked)
			if checked {
				g.globalInfo.ExtraHBAConf = []*v1.HBAConf{hbaConf}
			} else {
				g.globalInfo.ExtraHBAConf = []*v1.HBAConf{}
			}
		})

		generalForm.AddFormItem(sshGeneralCheckBox).AddFormItem(sshPort).AddFormItem(sshUser).AddFormItem(sshPasswd).AddFormItem(sshKeyFile).AddFormItem(sshConnect).AddFormItem(sshExecTime).
			AddFormItem(hbaCheckBox).AddFormItem(hbaType).AddFormItem(hbaDBName).AddFormItem(hbaDBUser).AddFormItem(hbaAddress).AddFormItem(hbaMethod)

		// 初始化参数.
		// 初始化参数
		// paramsCh := make(chan [][]string, 1)
		// go func() {
		// 	for paramsRows := range paramsCh {
		// 		initOps := []string{}
		// 		for _, value := range paramsRows {
		// 			log.Print("rows", value)
		// 			initOps = append(initOps, value[0])
		// 		}
		// 		g.globalInfo.GsInitdbOpts = initOps
		// 	}
		// }()
		initParams := g.createHasTableGrid1([]string{"参数", ""}, "初始化参数", true)

		envRowsCh := make(chan [][]string, 1)
		go func() {
			envRows := <-envRowsCh
			for _, envParam := range envRows {
				if _, ok := g.globalInfo.EnvMap[envParam[0]]; !ok {
					g.globalInfo.EnvMap[envParam[0]] = envParam[1]
				}

			}
		}()
		envParams := g.createHasTableGrid([]string{"key", "value", ""}, "环境变量", false, envRowsCh)

		g.advancedPage = tview.NewGrid().
			SetRows(38, 10, 10).
			SetColumns(0).
			AddItem(generalForm, 0, 0, 1, 1, 0, 0, true).
			AddItem(initParams, 1, 0, 1, 1, 0, 0, true).
			AddItem(envParams, 2, 0, 1, 1, 0, 0, true)
	}

	// 调整 rightPanel 的布局
	g.rightPanel.Clear().
		SetColumns(0, 0).                               // 调整为两列布局
		AddItem(g.globalPage, 0, 0, 1, 1, 0, 0, true).  // globalPage 占第一列
		AddItem(g.advancedPage, 0, 1, 1, 1, 0, 0, true) // advancedPage 占第二列

	// 切换到 rightPanel 并设置焦点
	g.pages.SwitchToPage("rightPanel")

	g.app.SetFocus(g.advancedPage)
}

// showAddDBInstance 显示新增数据库实例表单
func (g *Gui) showAddDBInstance() {
	dbInfo := &v1.DBServer{
		DBConf: make(map[string]string),
		EnvMap: make(map[string]string),
	}
	// 创建表单并添加保存按钮
	form := g.createDBForm(dbInfo)

	saveButton := tview.NewButton("保存").SetLabelColor(tcell.Color191)
	saveButton.SetSelectedFunc(func() {
		// 保存数据库实例信息，并在树状结构中添加子节点
		g.dbServers[dbInfo.Host] = dbInfo
		newNode := tview.NewTreeNode(dbInfo.Host).SetSelectedFunc(func() {
			g.showDBInfo(dbInfo.Host) // 点击子节点时展示对应页面
		})
		g.dbServerNode.AddChild(newNode)

		if g.isInstallCM {
			g.cmServers[dbInfo.Host] = &v1.CMServer{Host: dbInfo.Host, Port: 15300}
			newCMNode := tview.NewTreeNode(dbInfo.Host).SetSelectedFunc(func() {
				cmGrid := g.createCMForm(g.cmServers[dbInfo.Host])
				cmDel := tview.NewButton("删除").SetLabelColor(tcell.ColorRed)
				cmDel.SetSelectedFunc(func() {
					g.deleteCMNode(dbInfo.Host)
				})
				cmShowGrid := tview.NewGrid().
					SetRows(4, 1).
					SetColumns(1, 1, 10).
					AddItem(cmGrid, 0, 0, 4, 10, 0, 0, true).
					AddItem(returnButtonGrid(cmDel), 4, 1, 1, 2, 0, 0, true)
				g.cmPage[dbInfo.Host] = cmShowGrid
				g.showCMInfo(dbInfo.Host) // 点击子节点时展示对应页面
			})

			g.cmServerNode.AddChild(newCMNode)
		}

		// 创建并添加数据库信息页面
		g.createDBInfoPage(dbInfo)

		// Return to the globalPage view
		g.rightPanel.Clear().SetColumns(0, 0).
			AddItem(g.globalPage, 0, 0, 1, 2, 0, 0, true)

		g.pages.SwitchToPage("rightPanel")
		g.app.SetFocus(g.globalPage)
	})

	// 先创建 Grid 并赋值给 g.dbPage[dbInfo.Host]
	dbPage := tview.NewGrid().
		SetRows(11, 1, 2, 1).
		SetColumns(1, 1, 10).
		AddItem(form, 0, 0, 1, 10, 0, 0, true).
		AddItem(returnButtonGrid(saveButton), 3, 0, 1, 3, 0, 0, true)

	// 然后再设置高级选项按钮的回调
	advancedButton := tview.NewButton("高级选项").SetSelectedFunc(func() {
		g.dbPage[dbInfo.Host] = dbPage
		g.showAdvancedOptionsForDBInstance(dbInfo)
	})

	// 最后把 advancedButton 添加到 Grid 中
	dbPage.AddItem(returnButtonGrid(advancedButton), 1, 0, 1, 3, 0, 0, true)
	g.dbPage[dbInfo.Host] = dbPage
	// 在 rightPanel 中调整布局，确保 globalPage 在第一列，dbPage 在第二列
	g.rightPanel.Clear().
		SetColumns(0, 0).                              // 设置为两列布局
		AddItem(g.globalPage, 0, 0, 1, 1, 0, 0, true). // globalPage 占第一列
		AddItem(dbPage, 0, 1, 1, 1, 0, 0, true)        // dbPage 占第二列

	g.pages.SwitchToPage("rightPanel")
	g.app.SetFocus(g.dbPage[dbInfo.Host])
}

// showAdvancedOptionsForDBInstance 显示数据库实例的高级选项页面
func (g *Gui) showAdvancedOptionsForDBInstance(dbInfo *v1.DBServer) {
	// advPage := fmt.Sprintf("adv_%s", dbInfo.Host)
	log.Printf("Attempting to show advanced options for DB: %s", dbInfo.Host)

	_, ok := g.dbAdvancedPages[dbInfo.Host]

	if !ok {
		// 创建一个form
		dbInfo.AzName = "az1"
		dbInfo.AzPriority = 1
		azForm := tview.NewForm().AddInputField("可用区", dbInfo.AzName, 20, nil, func(text string) {
			dbInfo.AzName = text
		}).AddInputField("优先级", strconv.Itoa(dbInfo.AzPriority), 20, g.checkNum, func(text string) {
			num, err := strconv.Atoi(text)
			if err == nil {
				dbInfo.AzPriority = num
			}
		})

		newAdvGrid := tview.NewGrid().SetRows(3, 1, 1, 1, 2).SetColumns(1, 1, 10)

		// 创建 SSH Grid 和 SSH 配置信息
		sshGrid, sshOpt := g.createSSHGird(dbInfo.Host)
		dbInfo.SSHOption = sshOpt

		// 环境变量
		// var envRows [][]string
		envRowsCh := make(chan [][]string, 1)
		go func() {
			envRows := <-envRowsCh
			for _, envParam := range envRows {
				dbInfo.EnvMap[envParam[0]] = envParam[1]
			}
		}()
		envParams := g.createHasTableGrid([]string{"key", "value", ""}, "环境变量", false, envRowsCh)

		// 数据库参数
		// var dbRows [][]string
		dbParamsCh := make(chan [][]string, 1)
		go func() {
			dbRows := <-dbParamsCh
			for _, dbParam := range dbRows {
				dbInfo.DBConf[dbParam[0]] = dbParam[1]
			}
		}()
		dbParams := g.createHasTableGrid([]string{"key", "value", ""}, "数据库参数", false, dbParamsCh)

		// 创建保存按钮
		// saveButton := tview.NewButton("保存").SetSelectedFunc(func() {
		//
		//
		// 	g.rightPanel.Clear().
		// 		SetColumns(0, 0).
		// 		AddItem(g.globalPage, 0, 0, 1, 1, 0, 0, true). // globalPage 占第一列
		// 		AddItem(g.dbPage[dbInfo.Host], 0, 1, 1, 1, 0, 0, true) // dbPage 占第二列
		// 	g.app.SetFocus(g.rightPanel)
		// })

		// 创建返回按钮
		returnButton := tview.NewButton("返回").SetSelectedFunc(func() {
			g.dbAdvancedPages[dbInfo.Host] = newAdvGrid
			g.rightPanel.Clear().
				SetColumns(0, 0).
				AddItem(g.globalPage, 0, 0, 1, 1, 0, 0, true).         // globalPage 占第一列
				AddItem(g.dbPage[dbInfo.Host], 0, 1, 1, 1, 0, 0, true) // dbPage 占第二列
			g.app.SetFocus(g.rightPanel)
		})

		newAdvGrid.
			AddItem(azForm, 0, 0, 3, 11, 0, 0, true).
			AddItem(sshGrid, 3, 1, 1, 10, 0, 0, true).
			AddItem(envParams, 5, 1, 2, 10, 0, 0, true).
			AddItem(dbParams, 7, 1, 2, 10, 0, 0, true).
			// AddItem(returnButtonGrid(saveButton), 10, 0, 1, 1, 0, 0, true).
			AddItem(returnButtonGrid(returnButton), 10, 0, 1, 3, 0, 0, true)

		g.dbAdvancedPages[dbInfo.Host] = newAdvGrid
	}

	// 调整 rightPanel 的布局为三列
	g.rightPanel.Clear().
		SetColumns(0, 0, 0).                                            // 设置为三列布局
		AddItem(g.globalPage, 0, 0, 1, 1, 0, 0, true).                  // globalPage 占第一列
		AddItem(g.dbPage[dbInfo.Host], 0, 1, 1, 1, 0, 0, true).         // dbPage 占第二列
		AddItem(g.dbAdvancedPages[dbInfo.Host], 0, 2, 1, 1, 0, 0, true) // advancedPage 占第三列

	g.app.SetFocus(g.rightPanel)
}

var roleMap = map[string]string{
	"主库":   "primary",
	"备库":   "standby",
	"级联备库": "cascade_standby",
}

// createDBForm 创建数据库实例表单的输入框部分
func (g *Gui) createDBForm(dbInfo *v1.DBServer) *tview.Form {
	form := tview.NewForm()

	form.AddInputField("数据库IP", dbInfo.Host, 20, nil, func(text string) {
		if text != "" {
			dbInfo.Host = text
		}
	})

	role := tview.NewDropDown().SetLabel("角色")
	roleList := []string{"主库", "备库", "级联备库"}

	// 根据是否已经存在主库来设置默认选项
	defaultIndex := 0
	log.Println("is primary ", g.hasPrimary(), dbInfo.Host)
	if g.hasPrimary() && dbInfo.Host == "" {
		defaultIndex = 1 // 如果已经有主库，则默认选择备库
	}
	role.SetOptions(roleList, func(text string, index int) {
		if dbInfo.Host == "" {
			if index == defaultIndex {
				dbInfo.Role = roleMap[text]
			} else if index == 1 {
				dbInfo.Role = roleMap[text]
			} else {
				dbInfo.Role = roleMap[text]
			}
		}
	})
	if dbInfo.Host != "" {
		for i, _ := range roleList {
			if dbInfo.Role == roleMap[roleList[i]] {
				role.SetCurrentOption(i)
			}
		}
	} else {
		role.SetCurrentOption(defaultIndex)
	}

	// 上游实例下拉框
	var upstreamDropDown *tview.DropDown
	role.SetSelectedFunc(func(text string, index int) {
		dbInfo.Role = roleMap[text]
		if text == "级联备库" {
			if upstreamDropDown == nil {
				upstreamOPtions := g.getStandby()
				if len(upstreamOPtions) == 0 {
					upstreamOPtions = []string{"无可用上游实例"}
				}
				upstreamDropDown = tview.NewDropDown().SetLabel("上游实例").SetOptions(upstreamOPtions, func(text string, index int) {
					dbInfo.UpstreamHost = text
				})
			}
			form.AddFormItem(upstreamDropDown)
		} else {
			if upstreamDropDown != nil {
				form.RemoveFormItem(form.GetFormItemIndex("上游实例"))
				upstreamDropDown = nil
				dbInfo.UpstreamHost = ""
			}
		}
	})

	form.AddFormItem(role)

	form.
		AddInputField("用户名", g.globalInfo.User, 20, nil, func(text string) {
			if text != "" {
				dbInfo.User = text
			}
		}).
		AddInputField("用户组", g.globalInfo.Group, 20, nil, func(text string) {
			if text != "" {
				dbInfo.Group = text
			}
		}).
		AddInputField("数据库端口", "26000", 20, g.checkNum, func(text string) {
			port, err := strconv.Atoi(text)
			if err == nil {
				dbInfo.DBPort = port
			}
		})

	return form
}

// createDBInfoPage 创建数据库实例的信息页面
func (g *Gui) createDBInfoPage(dbInfo *v1.DBServer) {
	form := g.createDBForm(dbInfo)
	// 创建删除按钮
	deleteButton := tview.NewButton("删除").SetSelectedFunc(func() {
		// 删除树节点和页面，然后切换回全局配置页面
		g.deleteDBNode(dbInfo.Host)
	}).SetLabelColor(tcell.ColorRed)
	dbPage := tview.NewGrid().SetColumns(0, 6)
	// 添加高级选项按钮
	advancedButton := tview.NewButton("高级选项").SetSelectedFunc(func() {
		// 在点击高级选项时，跳转到高级选项页面
		// g.pages.AddPage(fmt.Sprintf("dbPage_%s", dbInfo.Host), dbPage, true, true)
		g.dbPage[dbInfo.Host] = dbPage
		g.showAdvancedOptionsForDBInstance(dbInfo)
	})
	dbPage.
		SetRows(11, 1, 2, 1).
		SetColumns(1, 1, 10).
		AddItem(form, 0, 0, 1, 10, 0, 0, true).
		AddItem(returnButtonGrid(advancedButton), 1, 1, 1, 2, 0, 0, true).
		AddItem(returnButtonGrid(deleteButton), 3, 1, 1, 2, 0, 0, true)
	g.dbPage[dbInfo.Host] = dbPage
}

// showDBInfo 显示数据库实例的信息页面
func (g *Gui) showDBInfo(host string) {
	if page, ok := g.dbPage[host]; ok {
		// 清除并重新布局 rightPanel
		g.rightPanel.Clear().
			SetColumns(0, 0).                              // 设置为两列布局
			AddItem(g.globalPage, 0, 0, 1, 1, 0, 0, true). // globalPage 占第一列
			AddItem(page, 0, 1, 1, 1, 0, 0, true)          // 将 page 显示在第二列

		g.app.SetFocus(page) // 设置焦点到 dbPage
	} else {
		// 如果页面不存在，显示全局配置
		g.app.SetFocus(g.globalPage)
	}
}
func (g *Gui) createCMForm(cmServer *v1.CMServer) *tview.Grid {
	cmOption := &v1.CMOption{CmServerPort: 15300, CmServerConf: map[string]string{}, CmAgentConf: map[string]string{}}
	if g.globalInfo.CMOption != nil {
		cmOption = g.globalInfo.CMOption
	}

	// generalCMGrid := tview.NewGrid().SetRows(1, 4, 4)
	cmDir := tview.NewInputField()
	if g.globalInfo.CMOption != nil && g.globalInfo.CMOption.Dir != "" {
		cmDir.SetText(g.globalInfo.CMOption.Dir)
	}
	cmDir.SetLabel("CM 安装目录").SetFieldWidth(20).SetChangedFunc(func(text string) {
		cmOption.Dir = text
	})
	// var cmRows [][]string
	cmRoesCh := make(chan [][]string, 1)
	go func() {
		cmRows := <-cmRoesCh
		for _, row := range cmRows {
			cmOption.CmServerConf[row[0]] = row[1]
		}
	}()
	cmServerConf := g.createHasTableGrid([]string{"key", "value", ""}, "CM 服务器配置", false, cmRoesCh)

	cmARowCh := make(chan [][]string, 1)
	go func() {
		cmARows := <-cmARowCh
		for _, row := range cmARows {
			cmOption.CmAgentConf[row[0]] = row[1]
		}
	}()
	cmAgentConf := g.createHasTableGrid([]string{"key", "value", ""}, "CM 代理配置", false, cmARowCh)

	g.globalInfo.CMOption = cmOption

	cmServer.Port = cmOption.CmServerPort

	form := tview.NewForm().
		AddInputField("CM IP    ", cmServer.Host, 20, nil, func(text string) {
			cmServer.Host = text
		}).
		AddInputField("CM端口    ", strconv.Itoa(cmServer.Port), 20, g.checkNum, func(text string) {
			atoi, err := strconv.Atoi(text)
			if err == nil {
				cmServer.Port = atoi
			}
		}).
		AddInputField("冗余 IP   ", "", 20, nil, func(text string) {
			cmServer.HAIPs = []string{text}
		})

	sshGrid, ssOpt := g.createSSHGird(cmServer.Host)
	cmServer.SSHOption = ssOpt

	cmGrid := tview.NewGrid().SetRows(1, 1, 1, 4, 4, 3).SetColumns(1, 1, 10).
		AddItem(cmDir, 0, 1, 1, 12, 0, 0, true).
		AddItem(form, 2, 0, 3, 12, 0, 0, true).
		AddItem(cmAgentConf, 5, 1, 4, 12, 0, 0, true).
		AddItem(cmServerConf, 9, 1, 4, 12, 0, 0, true).
		AddItem(sshGrid, 13, 2, 1, 12, 0, 0, true)

	return cmGrid
}

// createCMInfoPage 创建数据库实例的信息页面
func (g *Gui) createCMInfoPage(cmInfo *v1.CMServer) {
	cmForm := g.createCMForm(cmInfo)
	// 创建删除按钮
	deleteButton := tview.NewButton("删除").SetSelectedFunc(func() {
		// 删除树节点和页面，然后切换回全局配置页面
		g.deleteDBNode(cmInfo.Host)
	}).SetLabelColor(tcell.ColorRed)
	g.cmPage[cmInfo.Host] = tview.NewGrid()

	g.cmPage[cmInfo.Host].
		SetColumns(1, 1, 10).
		AddItem(cmForm, 0, 0, 1, 12, 0, 0, true).
		AddItem(returnButtonGrid(deleteButton), 1, 0, 1, 12, 0, 0, true)
}

// showDBInfo 显示数据库实例的信息页面
func (g *Gui) showCMInfo(host string) {
	if page, ok := g.cmPage[host]; ok {
		// 清除并重新布局 rightPanel
		g.rightPanel.Clear().
			SetColumns(0, 0).                              // 设置为两列布局
			AddItem(g.globalPage, 0, 0, 1, 1, 0, 0, true). // globalPage 占第一列
			AddItem(page, 0, 1, 1, 1, 0, 0, true)          // 将 page 显示在第二列

		g.app.SetFocus(page)
	} else {
		g.app.SetFocus(g.globalPage)
	}
}

// deleteCMNode 删除数据库节点和页面
func (g *Gui) deleteCMNode(ip string) {
	delete(g.cmServers, ip)
	// 删除树状结构中的节点
	for i := 0; i < len(g.cmServerNode.GetChildren()); i++ {
		if g.cmServerNode.GetChildren()[i].GetText() == ip {
			g.cmServerNode.RemoveChild(g.cmServerNode.GetChildren()[i])
			break
		}
	}

	// 删除后返回到 globalPage 占据两列的布局
	g.rightPanel.Clear().
		SetColumns(0, 0).
		AddItem(g.globalPage, 0, 0, 1, 2, 0, 0, true)

	g.pages.SwitchToPage("rightPanel")
	g.app.SetFocus(g.globalPage)
}

// deleteDBNode 删除数据库节点和页面
func (g *Gui) deleteDBNode(ip string) {

	delete(g.dbServers, ip)
	// 删除树状结构中的节点
	for i := 0; i < len(g.dbServerNode.GetChildren()); i++ {
		if g.dbServerNode.GetChildren()[i].GetText() == ip {
			g.dbServerNode.RemoveChild(g.dbServerNode.GetChildren()[i])
			break
		}
	}
	// 删除后返回到 globalPage 占据两列的布局
	g.rightPanel.Clear().
		SetColumns(0, 0).
		AddItem(g.globalPage, 0, 0, 1, 2, 0, 0, true)

	g.pages.SwitchToPage("rightPanel")
	g.app.SetFocus(g.globalPage)
}

// showAddCMInstance 显示新增CM实例表单
func (g *Gui) showAddCMInstance() {
	cmServer := &v1.CMServer{}
	cmForm := g.createCMForm(cmServer)

	saveButton := tview.NewButton("保存").SetLabelColor(tcell.Color191)
	saveButton.SetSelectedFunc(func() {

		// 保存数据库实例信息，并在树状结构中添加子节点
		g.cmServers[cmServer.Host] = cmServer
		newNode := tview.NewTreeNode(cmServer.Host).SetSelectedFunc(func() {
			cmGrid := g.createCMForm(g.cmServers[cmServer.Host])
			cmDel := tview.NewButton("删除").SetLabelColor(tcell.ColorRed)
			cmDel.SetSelectedFunc(func() {
				g.deleteCMNode(cmServer.Host)
			})
			cmShowGrid := tview.NewGrid().
				SetRows(4, 1).
				SetColumns(1, 1, 10).
				AddItem(cmGrid, 0, 0, 4, 10, 0, 0, true).
				AddItem(returnButtonGrid(cmDel), 4, 1, 1, 2, 0, 0, true)
			g.cmPage[cmServer.Host] = cmShowGrid

			g.showCMInfo(cmServer.Host) // 点击子节点时展示对应页面
		})
		g.cmServerNode.AddChild(newNode)

		// 切换回 globalPage 占据两列
		g.rightPanel.Clear().
			SetColumns(0, 0). // globalPage 占据两列
			AddItem(g.globalPage, 0, 0, 1, 2, 0, 0, true)

		g.pages.SwitchToPage("rightPanel")
		g.app.SetFocus(g.globalPage) // 将焦点设置回 globalPage
	})

	g.cmPage[cmServer.Host] = tview.NewGrid().
		SetRows(0, 0, 0).
		SetColumns(1, 10).
		AddItem(cmForm, 0, 0, 2, 12, 0, 0, true).
		AddItem(returnButtonGrid(saveButton), 2, 1, 1, 1, 0, 0, true)
	// 调整 rightPanel 的布局
	g.rightPanel.Clear().
		SetColumns(0, 0).                                        // 调整为两列布局
		AddItem(g.globalPage, 0, 0, 1, 1, 0, 0, true).           // globalPage 占第一列
		AddItem(g.cmPage[cmServer.Host], 0, 1, 1, 1, 0, 0, true) // cmPage 占第二列

	g.app.SetFocus(g.cmPage[cmServer.Host])
}

func (g *Gui) createSSHGird(ip string) (*tview.Grid, *v1.SSHOption) {
	sshGrid := tview.NewGrid()
	sshText := tview.NewTextView().SetLabel("连接信息:").SetLabelWidth(10)
	sshUpdateButton := tview.NewButton("编辑")
	sshUpdateButton.SetRect(0, 0, 10, 10)
	sshOption := &v1.SSHOption{
		Host:        ip,
		Port:        22,
		User:        "root",
		ConnTimeout: 60 * time.Second,
		ExecTimeout: 600 * time.Second,
	}
	selectedFunc := func() {
		form := tview.NewForm()

		form.AddInputField("服务器端口", strconv.Itoa(sshOption.Port), 20, g.checkNum, func(text string) {
			port, err := strconv.Atoi(text)
			if err == nil {
				sshOption.Port = port
			}
		})
		form.AddInputField("登录用户", sshOption.User, 20, nil, func(text string) {
			sshOption.User = text
		})
		form.AddInputField("登录密码", "", 20, nil, func(text string) {
			sshOption.Password = text
		})
		form.AddInputField("秘钥文件路径", "", 20, nil, func(text string) {
			sshOption.KeyFile = text
		})
		log.Println("moren shij ", sshOption.ConnTimeout)
		form.AddInputField("超时时间（m）", durationToMinutesStr(sshOption.ConnTimeout), 20, g.checkNum, func(text string) {
			duration, err := stringToDuration(text)
			if err == nil {
				sshOption.ConnTimeout = duration
			}
		})
		form.AddInputField("命令超时时间（m）", durationToMinutesStr(sshOption.ExecTimeout), 20, g.checkNum, func(text string) {
			duration, err := stringToDuration(text)
			if err == nil {
				sshOption.ExecTimeout = duration
			}
		})
		form.AddButton("保存", func() {
			sshText.SetText(fmt.Sprintf("%s@%s", sshOption.User, sshOption.Host))
			g.pages.RemovePage("modal")
			g.pages.SwitchToPage("rightPanel")

		}).AddButton("取消", func() {
			g.pages.RemovePage("modal")
			g.pages.SwitchToPage("rightPanel")

		})
		form.SetBorder(true)
		g.pages.AddPage("modal", NewModalForFlex(form, 50, 20), true, true)
	}

	sshUpdateButton.SetSelectedFunc(selectedFunc)

	sshGrid.SetRows(1).SetColumns(15, 5, 15, 5).
		AddItem(sshText, 0, 0, 1, 3, 0, 0, true).
		AddItem(returnButtonGrid(sshUpdateButton), 0, 4, 1, 1, 0, 0, true)
	return sshGrid, sshOption
}

func stringToDuration(minute string) (time.Duration, error) {
	log.Println("bbbbb", minute)
	minutes, err := strconv.Atoi(minute)
	if err != nil {
		return 0, err
	}
	return time.Duration(minutes) * time.Minute, nil
}

func durationToMinutesStr(durationStr time.Duration) string {
	log.Println("aaaaa", durationStr)
	minutes := int(durationStr.Minutes())
	return strconv.Itoa(minutes)
}

func InsertFormItem(form *tview.Form, index int, item tview.FormItem) {
	itemCount := form.GetFormItemCount()

	newItems := make([]tview.FormItem, 0)

	for i := 0; i < itemCount; i++ {
		if i == index {
			newItems = append(newItems, item)
		}
		newItems = append(newItems, form.GetFormItem(i))
	}

	if index >= itemCount {
		newItems = append(newItems, item)
	}

	form.Clear(false)
	for _, newItem := range newItems {
		form.AddFormItem(newItem)
	}
}

func (g *Gui) checkNum(textToCheck string, lastChar rune) bool {
	// 只接受数字字符
	return lastChar >= '0' && lastChar <= '9'
}

// NewModalForFlex 使用 Flex 布局创建一个模态框来包含表单
func NewModalForFlex(p tview.Primitive, width, height int) tview.Primitive {
	return tview.NewFlex().AddItem(nil, 0, 1, false).
		AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
			AddItem(nil, 0, 1, false).
			AddItem(p, height, 1, true).
			AddItem(nil, 0, 1, false), width, 1, true).
		AddItem(nil, 0, 1, false)
}

func (g *Gui) createHasTableGrid1(tableHeader []string, Label string, haveOneInput bool) *tview.Grid {
	gTbale := tview.NewGrid()

	table := gui.NewTable(tableHeader)
	table.SetBorder(true)
	table.InitHeaders()
	addButton := tview.NewButton("新增")
	addButton.SetBackgroundColor(tcell.ColorRed).SetTitleColor(tcell.ColorGreen)

	selectedFunc := func() {
		form := tview.NewForm()
		var userInputRows [][]string
		if haveOneInput {
			form.AddInputField("初始化参数", "", 20, nil, func(text string) {
				userInputRows = [][]string{{text}}
			})
		} else {
			var currentKey, currentValue string
			form.AddInputField("key", "", 20, nil, func(text string) {
				currentKey = text
				userInputRows = [][]string{{currentKey, currentValue}}
			})
			form.AddInputField("value", "", 20, nil, func(text string) {
				currentValue = text
				userInputRows = [][]string{{currentKey, currentValue}}
			})
		}

		form.AddButton("保存", func() {
			// g.globalInfo.GsInitdbOpts

			for _, value := range userInputRows {
				g.globalInfo.GsInitdbOpts = append(g.globalInfo.GsInitdbOpts, value[0])
			}

			table.SetRowInfo(userInputRows)
			// table.Refresh()

			g.pages.RemovePage("modal")
			g.app.SetFocus(g.pages.ShowPage("main"))
		}).AddButton("取消", func() {
			g.pages.RemovePage("modal")
			g.app.SetFocus(g.pages.ShowPage("main"))
		})

		form.SetBorder(true)
		g.pages.AddPage("modal", NewModalForFlex(form, 40, 10), true, true)
	}

	addButton.SetSelectedFunc(selectedFunc)
	text := tview.NewTextView().SetLabel(Label).SetSize(1, 6)
	gTbale.SetRows(1, 3, 1).SetColumns(0, 0, 0, 0, 0, 0).
		AddItem(text, 0, 0, 1, 6, 0, 0, true).
		AddItem(table, 1, 0, 3, 6, 0, 0, true).
		AddItem(returnButtonGrid(addButton), 4, 0, 1, 6, 0, 0, true)
	return gTbale
}

func (g *Gui) createHasTableGrid(tableHeader []string, Label string, haveOneInput bool, resultCh chan [][]string) *tview.Grid {
	gTbale := tview.NewGrid()

	table := gui.NewTable(tableHeader)
	table.SetBorder(true)
	table.InitHeaders()
	addButton := tview.NewButton("新增")
	addButton.SetBackgroundColor(tcell.ColorRed).SetTitleColor(tcell.ColorGreen)

	selectedFunc := func() {
		form := tview.NewForm()
		var userInputRows [][]string
		if haveOneInput {
			form.AddInputField("初始化参数", "", 20, nil, func(text string) {
				userInputRows = [][]string{{text}}
			})
		} else {
			var currentKey, currentValue string
			form.AddInputField("key", "", 20, nil, func(text string) {
				currentKey = text
				userInputRows = [][]string{{currentKey, currentValue}}
			})
			form.AddInputField("value", "", 20, nil, func(text string) {
				currentValue = text
				userInputRows = [][]string{{currentKey, currentValue}}
			})
		}

		form.AddButton("保存", func() {
			// g.globalInfo.GsInitdbOpts
			// 通过 channel 发送数据
			resultCh <- userInputRows
			table.SetRowInfo(userInputRows)
			// table.Refresh()

			g.pages.RemovePage("modal")
			g.app.SetFocus(g.pages.ShowPage("main"))
		}).AddButton("取消", func() {
			g.pages.RemovePage("modal")
			g.app.SetFocus(g.pages.ShowPage("main"))
		})

		form.SetBorder(true)
		g.pages.AddPage("modal", NewModalForFlex(form, 40, 10), true, true)
	}

	addButton.SetSelectedFunc(selectedFunc)
	text := tview.NewTextView().SetLabel(Label).SetSize(1, 6)
	gTbale.SetRows(1, 3, 1).SetColumns(0, 0, 0, 0, 0, 0).
		AddItem(text, 0, 0, 1, 6, 0, 0, true).
		AddItem(table, 1, 0, 3, 6, 0, 0, true).
		AddItem(returnButtonGrid(addButton), 4, 0, 1, 6, 0, 0, true)
	return gTbale
}

func (g *Gui) hasPrimary() bool {
	for _, dbServer := range g.dbServers {
		if dbServer.Role == "primary" {
			return true
		}
	}
	return false
}

func (g *Gui) getStandby() []string {
	standbyList := []string{}
	for ip, server := range g.dbServers {
		if server.Role == "备库" {
			standbyList = append(standbyList, ip)
		}
	}
	return standbyList
}

func returnButtonGrid(button *tview.Button) *tview.Grid {
	grid := tview.NewGrid().
		SetColumns(0, 10, 0).
		SetRows(0, 1, 0).
		AddItem(button, 1, 1, 1, 1, 0, 0, true)
	return grid
}
